#include <iostream>
#include "udp_client.hpp"
#include "err.hpp"
using namespace std;
using namespace udp_client;

//127.0.0.1 本地回路，就表示的是当前的主机，通常进行本地通信或测试
//./client serverip serverport 
void Usage(string u)
{
    cout <<"Usage:\n\t"<< u << " serverip serverport" << endl;
}
int main(int argv, char *argc[])
{
    // UdpClient u; 
    // cout<<"me is client"<<endl;
    // 客户端访问服务器：需要知道服务器的IP地址和端口号port
    if (argv != 3)
    {
        Usage(argc[0]);
        exit(USAGE_ERROR);
    }
    string serverip = argc[1];
    uint16_t serverport = atoi(argc[2]);
    cout << "serverip:" << serverip << "serverport:" << serverport << endl;
    // 1.创建套接字--打开网络文件
    int sock = socket(AF_INET, SOCK_DGRAM, 0); // AF_INET：ipv4地址族 SOCK_DGRAM：数据报字节流，用于UDP
    if (sock < 0)
    {
        cerr << "socket create error：" << strerror(errno) << endl;
        exit(SOCKET_ERROR);
    }
    // 2.绑定客户端的IP地址和端口号
    /*client这里要不要bind呢？要的！socket通信的本质[clientip:clientport，serverip:serverport]。
      要不要自己bind呢？不需要自己bind，也不要自己bind，OS自动给我们进行bind--
      为什么？client的port要随机让OS分配防止client出现启动冲突。
      (不同的软件进行不同的时间点服务器访问时，端口号不同，因为端口号存在被占用的情况)。*/

    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    socklen_t len = sizeof(server);
    // 发信息--需要知道服务器的IP地址和端口号port
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());
    while (true)
    {
        // ①.发信息到服务器
        /*ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);*/
        // 获取信息
        // cout << "please Enter#";
        cout << "剑痴的服务器#";
        string message;
        getline(std::cin,message);  //遇到空格继续读取
        sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);
        //cout << "client send to massage success " << endl;
        // ②.接收服务器的信息-->发信息之前，得知道服务器的IP地址和端口号
        /*ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);*/
        char buffer[2048];
        struct sockaddr_in serverpeer;
        socklen_t serverlen = sizeof(serverpeer);
        int n = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&serverpeer, &serverlen);
        //cout << "client receive massage success " << endl;
        if (n > 0)
        {
            buffer[n] = 0;
        }else continue;
        //cout << "server echo#" << buffer << endl;
        cout<<buffer<<endl;
    }
    return 0;
}